package com.cskaoyan.javase.oop2._2polymorphic._2advantage;

/**
 * 研究多态现象的优缺点
 * 我们通过一个案例：
 * 科学家要收集动物的叫声去研究，先要收集猫，狗两种动物的叫声研究。
 * 随后又扩展到其它动物，最后又需要研究人类。
 *
 * 多态的优点:
 * 1.要实现多态必须要继承，而继承提高了代码复用率，提升了程序的可维护性。（继承保证）
 * 2.有了多态后，用父类引用指向不同子类对象，
 *      只需要调用同名方法，就能自动根据不同子类对象，得出不同的行为。
 *      这大幅度简化了代码，提升了程序的扩展性。（多态保证）
 *
 * 多态的缺点:
 * 父类引用会限制子类对象的访问范围
 * 这时就无法访问子类独有成员了
 *
 *
 * 那么以上缺点问题如何解决?
 * 之所以存在上述问题,是因为引用是父类类型,限制了子类对象
 * 所以只需要把引用转换回子类引用,就能够解决了
 * 这个过程
 * 父类引用 --> 子类引用
 * 属于向下转型,属于强制类型转换
 * 语法:
 * 子类类名 引用名 = (子类类名)父类引用;
 *
 * 强制类型转换成功的前提:
 * 向下转型能够成功的前提是,强转后的引用,确实能够真的指向这个对象.
 * 具体来说:
 *      Grandfather gf = new Grandson();
 *      强转后的引用,要么就是之前父类引用指向的对象的类型(还原)
 *      Grandson gs = (Grandson) gf;
 *      强转后的引用,要么就是之前父类引用指向的对象的父类类型(这里仍然是父类引用指向子类对象)
 *      Father f = (Father) gf;
 *      Son s = (Son) gf;
 *
 * 强转如此危险,稍有不慎就会导致类型转换异常ClassCastException
 * 所以Java中有语法来帮助判断能否进行正常强转:
 * instanceof关键字
 * 用法:
 * 引用 instanceof 类名
 *
 * 含义是 判断左边引用所指向的对象,是否是后面类名的对象或者子类对象
 * 如果是,上述结构会返回true
 * 否者 返回false
 * 所以上述语法结构往往配合if使用
 * 一旦上述结构返回true 表示左边的引用可以强转成右边类名的引用
 *
 * 以后开发中,除非是百分百确定真的能够强转
 * 否则都建议使用instanceof关键字判断以后再做强转.
 *
 * @since 14:42
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        // collectCatVoice(new Cat());
        collectAnimalVoice(new Cat());
        collectAnimalVoice(new Dog());
        collectAnimalVoice(new Pig());
        collectAnimalVoice(new Person());
    }


    /*
        收集研究所有动物的叫声
     */
    public static void collectAnimalVoice(Animal a) {
        if (a instanceof Person) {
            // 表示a指向的对象要么就是Person对象
            // 要么就是Person的子类对象
            Person p = (Person) a;
            p.addMoney();
        }
        // 抓一只动物过来,让它叫
        a.shout();
        // 收集研究
    }
    /*
        先写一个方法收集研究猫的叫声
     */
   /* public static void collectCatVoice(Cat c) {
        // 抓一只猫过来,让它叫
        c.shout();
        // 收集研究
    }*/

}

class Animal {
    public void shout() {
        System.out.println("叫!");
    }
}

class Cat extends Animal {
    @Override
    public void shout() {
        System.out.println("喵喵喵~");
    }
}

class Dog extends Animal {
    @Override
    public void shout() {
        System.out.println("汪汪汪~");
    }
}

class Pig extends Animal {
    @Override
    public void shout() {
        System.out.println("小猪佩奇~~");
    }
}

class Person extends Animal {
    @Override
    public void shout() {
        System.out.println("嘤嘤嘤~~");
    }

    /*
        人是动物但又不同
        要想人配合研究 让他叫
        人需要给工资,给钱
        人就有独特的行为,要加钱,给钱才叫
     */
    public void addMoney() {
        System.out.println("给钱才叫!");
    }
}